#!/usr/bin/env python
# coding=utf-8
# @FileName :http_client.py
# @Time     :2022/2/15 9:52
# @Author   :ZXC
# @Desc     :
from datetime import datetime

import requests
import urllib3
from requests import Response, Request
from requests.exceptions import MissingSchema, InvalidSchema, InvalidURL, RequestException
from config.settings import logger

# 取消https请求的ssl告警
urllib3.disable_warnings()


class HttpSession(requests.Session):
    """
    执行HTTP请求，并在请求之间保存session、cookies。
    """

    def __init__(self):
        super(HttpSession, self).__init__()
        self.__init_response_meta()

    def __init_response_meta(self):
        """
        初始化meta数据，用于存储响应的详细数据
        Returns:

        """

        self.response_meta_data = {
            "response": {
                "url": "",
                "status_code": 200,
                "elapsed": 0,
                "cookies": {},
                "headers": {},
                "results": None,
                "content": None,
                "text": None,
            },
            "stat": {
                "execute_time": '',
            }
        }

    @staticmethod
    def _get_response_records(resp_obj):
        """
        从Response()对象中获取响应的信息
        Args:
            resp_obj: 响应对象

        Returns: 处理后的响应dict

        """

        # 响应字典
        response_dict = dict()

        # 获取响应信息
        response_dict["url"] = resp_obj.url
        response_dict["status_code"] = resp_obj.status_code
        # 响应时长（ms）
        response_dict["elapsed"] = resp_obj.elapsed.microseconds / 1000.0
        response_dict["cookies"] = resp_obj.cookies or {}
        response_dict["headers"] = dict(resp_obj.headers)

        content_type = dict(resp_obj.headers).get("Content-Type", '')
        if "application/json" in content_type:
            # 记录响应的json数据
            response_dict["results"] = resp_obj.json()
        elif "image" in content_type:
            response_dict["content"] = resp_obj.content
        else:
            text = resp_obj.text
            if len(text) > 512:
                response_dict["text"] = text[:512] + f'此处省略了 {len(text) - 512} 个字符……'
            else:
                response_dict["text"] = text

        return response_dict

    def request(self, method, url, **kwargs):
        """
        构造请并发送请求
        Args:
            method:
            url:
            **kwargs:

        Returns:

        """

        self.__init_response_meta()
        # 记录测试名称
        kwargs.setdefault("timeout", 120)

        # 执行时间
        execute_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.response_meta_data["stat"].update({"execute_time": execute_time})

        # 发送请求，并返回响应内容
        response = self._send_request_safe_mode(method, url, **kwargs)

        # 记录请求和响应，不包括30X重定向
        self.response_meta_data["response"] = self._get_response_records(response)

        try:
            response.raise_for_status()
        except RequestException as e:
            logger.error("exception：{}".format(str(e)))

        return self.response_meta_data

    def _send_request_safe_mode(self, method, url, **kwargs):
        """
        发送一个HTTP请求，并捕获由于连接问题可能发生的任何异常。
        Args:
            method:
            url:
            **kwargs:

        Returns:

        """

        try:
            verify = True
            # 处理https请求
            if 'https' == url.split(':', maxsplit=1)[0].lower():
                verify = False
            return requests.Session.request(self, method=method, url=url, verify=verify, **kwargs)
        except (MissingSchema, InvalidSchema, InvalidURL):
            raise
        except RequestException as e:
            r = HttpResponse()
            r.error = e
            r.status_code = 0  # with this status_code, content returns None
            r.request = Request(method, url).prepare()
            return r


class HttpResponse(Response):
    """
    HTTP请求响应对象
    """

    def raise_for_status(self):
        if hasattr(self, "error") and self.error:
            raise self.error
        Response.raise_for_status(self)


if __name__ == '__main__':
    s = HttpSession()
    s.request(
        method='GET',
        url='https://10.121.110.222/csam/asset/organize/findOrganizeTree',
        headers={
            "uid": 'cc41b6e1-9604-4e78-a59d-ab91d7384db6'
        }
    )
    print(s.response_meta_data)
